package ppd;


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.net.InetAddress;
import java.util.ArrayList;
import java.io.IOException;
import java.rmi.Naming; // ports autorises : 10061 a 10080
import java.io.StreamTokenizer;
import java.net.MalformedURLException;
import java.rmi.RemoteException;

/**
 *
 * @author Bastien
 */
public class Main {

    public static void main(String args[]) throws IOException, DotFormatException{

        boolean objetACreer=false;
        boolean objetCree=false;
        int capacite=0;
        TableImpl t=null;
        String localIp= InetAddress.getLocalHost().getHostAddress();
        String ipSrc=null;
        String ipDest=null;
        boolean barmanCree=false;
        Thread barman= null;
        ArrayList<String> voisins=new ArrayList<String>();


        System.out.println("Localhost: "+localIp);
        StreamTokenizer tok=null;
        if(args.length<1){ System.err.print("Veuillez entrer en argument de la ligne de commande le fichier dot contenant le graphe."); System.exit(0);}
        System.out.println("Args 0 = "+args[0]);
        try{
            
            tok = new StreamTokenizer(new FileReader(args[0])); //On lit le fichier dot dont le nom est passe en parametre a la ligne de commande
        }
        catch(FileNotFoundException e){
            System.out.println("ERREUR: Fichier non trouve.");
        }
        String lu=null;
        String[] decoupee=null;
        tok.nextToken();
        //On va lire le debut du fichier dot qui contient "graph 'nomdugraphe'
        if(tok.ttype!=StreamTokenizer.TT_WORD || !tok.sval.equalsIgnoreCase("graph")) throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Trouve: "+tok+" alors que 'graph' etait attendu.");
        tok.nextToken();
        if(tok.ttype!=tok.TT_WORD) throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Touve : "+tok+" alors qu'un nom de graphe etait attendu.");
        tok.nextToken();
        if(tok.ttype!='{' ) throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Trouve :"+tok+" alors qu'une accolade ouvrante etait attendue");
        tok.nextToken();
        tok.eolIsSignificant(false);

        while(tok.ttype!='}' && tok.ttype!=tok.TT_EOF){

            decoupee=tok.sval.split(" ");
            ipSrc=decoupee[0]; //On a recupere l'adresse IP
            //System.out.println("Ip Source Lue : "+ipSrc);
            if(ipSrc.charAt(0)>='a' && ipSrc.charAt(0) <='z') //Si on a entre l'alias d'un pc au lieu de son IP
            {
                ipSrc = InetAddress.getByName(ipSrc).getHostAddress();
            }

            if(ipSrc.equalsIgnoreCase(localIp)){ //Si c'est notre IP que l'on vient de lire
                objetACreer=true;
                capacite=Integer.parseInt(decoupee[1]);
                    
				if(decoupee.length==3){ //S'il y a un "barman"
					if(!decoupee[2].equalsIgnoreCase("barman")) throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Trouve :"+decoupee[2]+" alors que le mot 'barman' etait attendu");
					if(!barmanCree){
						//System.out.println("Je cree un barman");
						barman=new Thread(new BarmanImpl()); //Je cree le barman qui est un Thread
						barmanCree=true;
					}
             	}
		 	}


            tok.nextToken(); //On doit etre sur le premier tiret
            if(tok.ttype!='-') throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Trouve :"+tok+" alors qu'un tiret etait attendu");
            tok.nextToken();
            if(tok.ttype!='-') throw new DotFormatException("Le format du fichier dot n'est pas conforme a nos specifications. Trouve :"+tok+" alors qu'un tiret etait attendu");
            tok.nextToken(); //On passe a la destination
               
                decoupee=tok.sval.split(" ");
                ipDest=decoupee[0];
                if(ipDest.charAt(0)>='a' && ipDest.charAt(0) <='z') //Si on a entre l'alias d'un pc au lieu de son IP
                {
                    ipDest = InetAddress.getByName(ipDest).getHostAddress();
                }


                //System.out.println("Ip Destination lue : "+ipDest);
                if(ipDest.equalsIgnoreCase(localIp)){ //Si c'est notre IP
                    if(ipSrc.equalsIgnoreCase(localIp)){ System.err.print("Vous ne pouvez relier un sommet a lui-meme."); tok.nextToken();} //Si nous sommes la source et la destination de l'arete
                    if(!objetCree){ //Si on a deja cree notre objet, il ne reste qu'a ajouter ipSrc comme un sommet auquel on est relie
                        t=new TableImpl(Integer.parseInt(decoupee[1]));
                        try{ //On enregistre la table dans le rmiregistry
                            Naming.rebind("//"+localIp+":10070/table", t);
                            //System.out.println("Enregistrement termine");
                        }
                        catch(MalformedURLException m){ System.err.println("L'url \"//"+localIp+":10070/table\" est mal formee."); System.exit(0);}
                        catch(RemoteException r){System.err.println("Une Exception de type RemoteException est survenue lors de l'enregistrement de l'objet dans l'annuaire local. Celui-ci semble ne pas s'etre lance correctement sur le port 10070."); System.exit(0);}
                        catch(Exception e){System.err.println("Une exception du type "+e.getClass()+" est survenue lors de l'enregistrement de l'objet dans le RmiRegistry... Arret du programme."); System.exit(0);}
                        objetCree=true;
                    }

                    //System.out.println("J'ajoute "+ipSrc+" comme voisin");
                    voisins.add(ipSrc);

                }
                else{ //Si je n'ai pas lu mon Ip, soit je suis la source et j'ajoute cette Ip comme voisin, soit je ne fais ien
                    if(ipSrc.equalsIgnoreCase(localIp)){ //Si je suis la source de l'arete
                        //System.out.println("J'ajoute "+ipDest+" comme voisin");
                        voisins.add(ipDest);
                    }
                }
        tok.nextToken();
        }
        
        if(objetACreer){ //Si je suis la table centrale, je m'inscris en dernier pour avoir le nombre de tables afin de creer la barriere
            t=new TableImpl(capacite, (voisins.size())+1); 
            try{ //On enregistre la table dans le rmiregistry
                Naming.rebind("//"+localIp+":10070/table", t);
                System.out.println("Enregistrement termine");
            } //J'enregistre mon buveur
            catch(MalformedURLException m){ System.err.println("L'url \"//"+localIp+":10070/table\" est mal formee."); System.exit(0);}
            catch(RemoteException r){System.err.println("Une Exception de type RemoteException est survenue lors de l'enregistrement de l'objet dans l'annuaire local. Celui-ci semble ne pas s'etre lance correctement sur le port 10070."); System.exit(0);}
            catch(Exception e){System.err.println("Une exception du type "+e.getClass()+" est survenue lors de l'enregistrement de l'objet dans le RmiRegistry... Arret du programme."); System.exit(0);}
        }
        
        for(String s : voisins){ //On va recuperer les objets distants de tous nos voisins
            t.addVoisin(s);
        }
        System.out.println("Le plan de la salle est termine, il ne reste plus qu'a attendre que le barman commence son service...");
        if(t!=null)	t.attendre(ipSrc); //On attend tous que la table centrale demarre

	if(barmanCree) barman.start();
	if(t!=null)	t.start();
    }
}

